<template>
  <div>
    <div ref='reference' h8 flex class="concave">
      <div flex-shrink-0 bg-cyan-5  w='1rem' flex items-center justify-center>T</div>
      <input class="search-input" w0 flex-basis-0 flex-1 border-none outline-none
        :class="{ 'search-active': active }"
        :placeholder="modelValue.name"
        v-model="searchInput"
        @focus="active = true"/>
    </div>
    <Teleport to="body">
      <div ref="floating" v-show="active" :style="floatingStyles" class="my-type-select">
        <div flex h-10 px2 items-center>
          <MyCheckBox :model-value="arrayEnabled" label="数组" @update:model-value="(v) => toggleArray(v as boolean)" />
          <!-- <ElCheckbox :model-value="arrayEnabled" label="数组" @change="(v) => toggleArray(v as boolean)"/> -->
          <div v-if="arrayDim > 0" flex items-center>
            <div mr1>({{ arrayDim }}维)</div>
            <div h4 w4 flex items-center justify-center class="my-action" @click="arrayDim += 1">
              <ElIconPlus />
            </div>
          </div>
        </div>
        <div of-auto flex-1 bg-gray-7>
          <div v-for="item in options" @click="selectType(item)" @dblclick="confirmType" p2 hover-bg="#ffffff40" :style="{
            background: selectedType.name === item.name ? '#00000040' : undefined
          }">
            {{ item.name }}
          </div>
        </div>
        <div flex h-10 px2 items-center>
          <ElButton @click="confirmType" type="primary" size="small" w-full>确认</ElButton>
        </div>
      </div>
    </Teleport>

  </div>

</template>

<script setup lang="ts">
import { autoUpdate, offset, useFloating } from '@floating-ui/vue';
import { onClickOutside } from '@vueuse/core';
import { GetAllBundles } from '~/models/pyBundles';
import { tAny, tNull, TypesInherent, TypesReceiveLiterial } from '~/models/types';
import { ListType } from '~/models/types/list_type';
import type { DataType } from '~/models/types/type';
import { oProject, oStorage } from '~/models/Project';

const props = defineProps<{
  modelValue: DataType,
  explicit?: boolean
  options?: DataType[]
}>()

const reference = ref(null);
const floating = ref(null);
const { floatingStyles } = useFloating(reference, floating, {
  placement: 'bottom',
  whileElementsMounted: autoUpdate,
  middleware: [
    offset({
      mainAxis: 0,
      crossAxis: -2
    }),
  ]
});

const active = ref(false)
const searchInput = ref('')

onClickOutside(reference, () => {
  searchInput.value = ''
  active.value = false
}, {
  ignore: ['.my-type-select']
})

function calcDim(t: DataType) {
  let d = 0
  let _t = t
  while ((_t as any).itemType !== undefined) {
    d += 1
    _t = (_t as any).itemType
  }
  return d
}
function calcBaseType(t: DataType) {
  let _t = t
  while ((_t as any).itemType !== undefined) {
    _t = (_t as any).itemType
  }
  return _t
}

const arrayDim = ref(calcDim(props.modelValue))
const arrayEnabled = computed(() => arrayDim.value !== 0)
function toggleArray(enable: boolean) {
  console.log(enable);

  if (enable) {
    arrayDim.value = 1
  }
  else {
    arrayDim.value = 0
  }
}

// const grammarTypes = [
//   new ListType(tAny)
// ]
const typesFromModules = computed(() => lodash.flatten(GetAllBundles()
  .filter(m => oProject.value!.modulesEnabled.includes(m.name))
  .map(m => m.typeDeclares)))
const options = computed(() => {
  const allTypes = props.options ? props.options : [
    ...TypesInherent,
    ...typesFromModules.value,
    // ...grammarTypes,
  ]
  return allTypes.filter(t => {
    if (!props.explicit) {
      return true
    }
    else {
      return !t.name.includes('any') && !t.name.includes('|')
    }
  }).filter(x => {
    if (!searchInput.value) {
      return true
    }
    return x.name.toLowerCase().includes(searchInput.value.toLowerCase())
  })
})

const emit = defineEmits<{
  (e: 'update:modelValue', event: DataType): void,
}>()


function isListType(t: DataType): t is ListType {
  return t.name.includes('[]')
}

const selectedType = ref(calcBaseType(props.modelValue))
function selectType(t: DataType) {
  selectedType.value = t
}

function confirmType() {
  // 检查数组维数
  let _t = selectedType.value
  for (let i = 0; i < arrayDim.value; i++) {
    _t = new ListType(_t)
  }
  emit('update:modelValue', _t)
  active.value = false
}
</script>

<style lang="scss">
.el-popper:has(> .my-type-select) {
  padding: 0;
  overflow: hidden;
}

.my-type-select {
  background: var(--bg-body);
  box-shadow: var(--shadow-convex);
  padding: 2px;
  width: 120px;
  display: flex;
  flex-direction: column;
  z-index: 10000;
  border: none;
}

.search-input {
  padding: 0 0.5rem;
  color: var(--color-content);
  &::placeholder {
    color: var(--color-content);
  }
}

.search-active {
  &::placeholder {
    color: gray;
  }
}
</style>